package com.gitee.feizns.dynamic.reflect;

import com.gitee.feizns.dynamic.ExUtils;

import java.lang.reflect.Constructor;
import java.util.Deque;

/**
 * <b>构造器操作工具类</b>
 * @author feizns
 * @since 2019/5/19 0019
 */
public abstract class ConstructorUtils {

    /**
     * <b>使用参数params实例化type类型</b>
     * @param type {@link Class}
     * @param params 参数列表
     * @param <T> 需要实例化的类型
     * @return 对应类型的实例
     */
    public static <T> T newInstance(Class<T> type, Object... params) {
        return ExUtils.ignore(() -> constructor(type, ClassUtils.getClasses(params)).newInstance(params));
    }

    /**
     * <b>获取对应参数的公共构造方法</b>
     * @param type 类型
     * @param parameterTypes 参数类型
     * @return {@link Constructor}
     */
    public static <T> Constructor<T> constructor(Class<T> type, Class<?>... parameterTypes) {
        return ExUtils.ignore(() -> type.getConstructor(parameterTypes));
    }

    /**
     * 找到可以调用单个参数构造函数
     * @param type 类型
     * @param parameterType 参数类型
     * @return {@link Constructor}<{@link T}>
     */
    public static <T> Constructor<T> findCanInvokeSingleParameterConstructor(Class<T> type, Class<?> parameterType) {
        Deque<Class<?>> classesAndInterfaces = ClassUtils.getClassesAndInterfaces(parameterType);
        while ( !classesAndInterfaces.isEmpty() ) {
            Class<?> remove = classesAndInterfaces.remove();
            Constructor<T> result = constructor(type, remove);
            if ( result != null )
                return result;
        }
        return null;
    }

}
